package com.mdb.util;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class ClassUtils {
	public static List<Class<?>> findClasses(String packageName) throws Exception {
		return new ClassFinder(packageName).getClasses();
	}

	public static <T> List<Class<T>> findClasses(String packageName, Class<T> classType, int containsModifiers, int exceptModifiers) throws Exception {
		List<Class<?>> classes = findClasses(packageName);

		List<Class<T>> results = new ArrayList<Class<T>>();
		for (Class cls : classes) {
			if (((classType != null) && (!classType.isAssignableFrom(cls))) || ((cls.getModifiers() & containsModifiers) != containsModifiers) || ((cls.getModifiers() & exceptModifiers) != 0))
				continue;
			results.add(cls);
		}

		return results;
	}

	public static PropertyDescriptor[] getBeanPropertyDescriptors(Class<?> beanClass) throws IntrospectionException {
		return getBeanPropertyDescriptors(beanClass);
	}

	public static PropertyDescriptor[] getBeanPropertyDescriptors(Class<?> beanClass, String[] filterFields) throws IntrospectionException {
		BeanInfo beanInfo = Introspector.getBeanInfo(beanClass);

		PropertyDescriptor[] props = beanInfo.getPropertyDescriptors();
		List propList = new ArrayList();

		Set filterSet = new HashSet();
		Collections.addAll(filterSet, filterFields);

		for (PropertyDescriptor prop : props) {
			if ("class".equals(prop.getName())) {
				continue;
			}
			if ((filterSet.contains(prop.getName())) || (prop.getReadMethod() == null) || (prop.getWriteMethod() == null))
				continue;
			prop.getReadMethod().setAccessible(true);
			prop.getWriteMethod().setAccessible(true);
			propList.add(prop);
		}

		return (PropertyDescriptor[]) propList.toArray(new PropertyDescriptor[propList.size()]);
	}

	public static <T> Map<String, Object> beanToMap(T bean, String[] filterFields) throws Exception {
		PropertyDescriptor[] props = getBeanPropertyDescriptors(bean.getClass(), filterFields);

		Map beanMap = new LinkedHashMap();

		for (PropertyDescriptor prop : props) {
			String propName = prop.getName();

			Method getter = prop.getReadMethod();

			beanMap.put(propName, getter.invoke(bean, new Object[0]));
		}
		return beanMap;
	}
}
